package CalesRobot;

import battlecode.common.Clock;
import battlecode.common.Direction;
import battlecode.common.GameActionException;
import battlecode.common.MapLocation;
import battlecode.common.Robot;
import battlecode.common.RobotController;
import battlecode.common.TerrainTile;

public  class SoldierMovement {
	private static Boolean OUTPUT_DEBUG=false;
	public static void PerformMovement(RobotController rc,BOTInstanceVariables instanceVariables) throws GameActionException
	{
		instanceVariables.AddLocation(rc.getLocation());
		Direction dir=null;
		
		
		Direction battleDir=DirectionTowardTeamatesInBattle(rc);
		if(battleDir!=null)//If there is an enemy nearby, pursue them
		{
			if(OUTPUT_DEBUG)System.out.println("Going towards the enemy: "+battleDir);
			dir=battleDir;
		}
		
		if(dir==null)//If no other target has been acquired then go towards the enemy HQ
		{
			dir= AimAtEnemyHQ(rc,instanceVariables);		
		}
		
		if(OUTPUT_DEBUG)System.out.println("About to check for stuck case");
		
		if(StuckCase(rc,rc.getLocation().add(dir)) || !rc.canMove(dir)) //Check if they are surrounded by mines and people and cannot move
		{
			if(OUTPUT_DEBUG)System.out.println("Is a stuck case");
			dir=FindNearestMineDirection(rc,dir);
		}

		if(OUTPUT_DEBUG)System.out.println("About to check for mine");
		if (rc.senseMine(rc.getLocation().add(dir))!=null) //If there is a mine in the way defuse it
		{
			if(OUTPUT_DEBUG)System.out.println("Defusing mine");
			rc.defuseMine(rc.getLocation().add(dir));
		}
		
		
		if(OUTPUT_DEBUG)System.out.println("moving "+dir);
		
		
		if(rc.canMove(dir))
			rc.move(dir);
		else
		{
			if(OUTPUT_DEBUG)System.out.println("!!! Error state, tried to move "+dir+" but already moving");
		}
	}
	
	private static Direction DirectionTowardTeamatesInBattle(RobotController rc) throws GameActionException
	{
		Robot[] enemyRobots = rc.senseNearbyGameObjects(Robot.class,50,rc.getTeam().opponent());
		if(enemyRobots.length!=0) //Enemies Spotted
		{
			int closestDist = 50;
			MapLocation closestEnemy=null;
			for (int i=0;i<enemyRobots.length;i++){
				Robot arobot = enemyRobots[i];
				battlecode.common.RobotInfo arobotInfo = rc.senseRobotInfo(arobot);
				int dist = arobotInfo.location.distanceSquaredTo(rc.getLocation());
				if (dist<closestDist)
				{
					closestDist = dist;
					closestEnemy = arobotInfo.location;
				}
			}
			Direction dir = rc.getLocation().directionTo(closestEnemy);
			while (!(rc.senseMine(rc.getLocation().add(dir))==null && rc.canMove(dir))) 
			{
				dir = NextDir(dir, true);
			}
		}
		return null;
		
	}
	
	private static Direction FindNearestMineDirection(RobotController rc,Direction dir)
	{
		
		do
		{
			dir=NextDir(dir,true);
		}
		while(rc.senseMine(rc.getLocation().add(dir))==null);
		return dir;
	}
	
	private static  Boolean StuckCase(RobotController rc,MapLocation locationToMove) throws GameActionException
	{
		Robot[] teamRobots = rc.senseNearbyGameObjects(Robot.class,1,rc.getTeam());
		for(Robot bot : teamRobots)
		{
			battlecode.common.RobotInfo botInfo=rc.senseRobotInfo(bot);
			if(botInfo.location==locationToMove)
			{
				return true;
			}
		}
		return false;
	}
	
	private static Direction NextDir(Direction dir, boolean isClockwise) 
	{
		if (isClockwise) {
			if (dir == Direction.NORTH) {
				return Direction.NORTH_EAST;
			} else if (dir == Direction.NORTH_WEST) {
				return Direction.NORTH;
			} else if (dir == Direction.WEST) {
				return Direction.NORTH_WEST;
			} else if (dir == Direction.SOUTH_WEST) {
				return Direction.WEST;
			} else if (dir == Direction.SOUTH) {
				return Direction.SOUTH_WEST;
			} else if (dir == Direction.SOUTH_EAST) {
				return Direction.SOUTH;
			} else if (dir == Direction.EAST) {
				return Direction.SOUTH_EAST;
			} else if (dir == Direction.NORTH_EAST) {
				return Direction.EAST;
			}
		} else {
			if (dir == Direction.EAST) {
				return Direction.NORTH_EAST;
			} else if (dir == Direction.NORTH_EAST) {
				return Direction.NORTH;
			} else if (dir == Direction.NORTH) {
				return Direction.NORTH_WEST;
			} else if (dir == Direction.NORTH_WEST) {
				return Direction.WEST;
			} else if (dir == Direction.WEST) {
				return Direction.SOUTH_WEST;
			} else if (dir == Direction.SOUTH_WEST) {
				return Direction.SOUTH;
			} else if (dir == Direction.SOUTH) {
				return Direction.SOUTH_EAST;
			} else if (dir == Direction.SOUTH_EAST) {
				return Direction.EAST;
			}
		}
		
		return dir;
	}
	
	private static Direction AimAtLocation(RobotController rc,MapLocation loc,BOTInstanceVariables instanceVariables)
	{
		Direction dir = rc.getLocation().directionTo(loc);
		Direction initialDir=dir;
		while ((!(rc.senseMine(rc.getLocation().add(dir))==null && rc.canMove(dir))  )
				|| instanceVariables.HasRecentLocation(rc.getLocation().add(dir)))
		{
			
			if(OUTPUT_DEBUG)System.out.println("robot looking for RV location: "+dir+" initial:"+dir);
			dir = NextDir(dir, true);
			if(dir==initialDir)
				return dir;// its gone all the way around
			
		}
	
		return dir;
	}
	
	private static Direction AimAtEnemyHQ(RobotController rc,BOTInstanceVariables bic) {
		
		return AimAtLocation(rc,rc.senseEnemyHQLocation(),bic);
	}
	
	private static Direction AimAtRV(RobotController rc,BOTInstanceVariables bic) {
		MapLocation enemyLoc = rc.senseEnemyHQLocation();
		MapLocation ourLoc = rc.senseHQLocation();
		int x = (enemyLoc.x+3*ourLoc.x)/4;
		int y = (enemyLoc.y+3*ourLoc.y)/4;
		MapLocation rallyPoint = new MapLocation(x,y);
		return AimAtLocation(rc,rallyPoint,bic);
		
	}

}
